#include "stdafx.h"
#include "MainFrame.h"
#include "Renderer.h"
#include "Scene.h"
#include "MenuDialog.h"

CMainFrame::CMainFrame()
: m_pRenderer(NULL)
, m_pScene(NULL)
, m_pMenuDialog(NULL)
, m_bRenderGUI(true)
{
}

CMainFrame::~CMainFrame()
{
	delete m_pRenderer;
	delete m_pScene;

	delete m_pMenuDialog;
}

SDL_Surface& CMainFrame::InitSDL()
{
	atexit(SDL_Quit);

	if(SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		cerr << "Unable to initialise SDL: " << SDL_GetError();
		exit(0);
	}

	SDL_Surface* screen = SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 0, SDL_OPENGL);

	if(screen == 0)
	{
		cerr << "Unable to set OpenGL videomode: " << SDL_GetError();
		SDL_Quit();
		exit(0);
	}

	SDL_EnableUNICODE(1) ;
	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
	SDL_WM_SetCaption("RayTracer_chpark", "RayTracer_chpark");

	return *screen;
}

CEGUI::WindowManager& CMainFrame::InitCEGUI(SDL_Surface& surface)
{
	CEGUI::OpenGLRenderer::bootstrapSystem();

	SetCEGUIPaths();

	CEGUI::SchemeManager::getSingleton().create("TaharezLook.scheme");

	return CEGUI::WindowManager::getSingleton();
}

void CMainFrame::SetCEGUIPaths()
{
	CEGUI::DefaultResourceProvider& defaultResProvider =
		*static_cast<CEGUI::DefaultResourceProvider*>
		(CEGUI::System::getSingleton().getResourceProvider());

	const string strCEGUIInstallSharePath = strCEGUIInstallBasePath + "/datafiles/";

	cout << "Using scheme directory '" << strCEGUIInstallSharePath + "schemes/" << "'" << endl;

	defaultResProvider.setResourceGroupDirectory("schemes",		strCEGUIInstallSharePath + "schemes/");
	defaultResProvider.setResourceGroupDirectory("imagesets",	strCEGUIInstallSharePath + "imagesets/");
	defaultResProvider.setResourceGroupDirectory("fonts",		strCEGUIInstallSharePath + "fonts/");
	defaultResProvider.setResourceGroupDirectory("layouts",		strCEGUIInstallSharePath + "layouts/");
	defaultResProvider.setResourceGroupDirectory("looknfeels",	strCEGUIInstallSharePath + "looknfeel/");
	defaultResProvider.setResourceGroupDirectory("lua_scripts",	strCEGUIInstallSharePath + "lua_scripts/");
	defaultResProvider.setResourceGroupDirectory("schemas",		strCEGUIInstallSharePath + "xml_schemas/");
	defaultResProvider.setResourceGroupDirectory("animations",	strCEGUIInstallSharePath + "animations/");

	CEGUI::Imageset::setDefaultResourceGroup("imagesets");
	CEGUI::Font::setDefaultResourceGroup("fonts");
	CEGUI::Scheme::setDefaultResourceGroup("schemes");
	CEGUI::WidgetLookManager::setDefaultResourceGroup("looknfeels");
	CEGUI::WindowManager::setDefaultResourceGroup("layouts");
	CEGUI::ScriptModule::setDefaultResourceGroup("lua_scripts");
	CEGUI::AnimationManager::setDefaultResourceGroup("animations");

	CEGUI::XMLParser * parser = CEGUI::System::getSingleton().getXMLParser();
	if(parser->isPropertyPresent("SchemaDefaultResourceGroup"))
	{
		parser->setProperty("SchemaDefaultResourceGroup", "schemas");
	}
}

void CMainFrame::CreateGUI(CEGUI::WindowManager& winManager)
{
	m_pMenuDialog = new CMenuDialog(this);
	m_pMenuDialog->Load("menu.layout");
}

void CMainFrame::RenderGUI()
{
	if (m_bRenderGUI)
		CEGUI::System::getSingleton().renderGUI();
}

void CMainFrame::HandleInput(bool &bQuit)
{
	SDL_Event e;

	while(SDL_PollEvent(&e))
	{
		switch(e.type)
		{
		case SDL_MOUSEMOTION:
			CEGUI::System::getSingleton().injectMousePosition(
				static_cast<float>(e.motion.x), static_cast<float>(e.motion.y));
			break;

		case SDL_MOUSEBUTTONDOWN:
			HandleMouseDown(e.button.button);
			break;

		case SDL_MOUSEBUTTONUP:
			HandleMouseUp(e.button.button);
			break;

		case SDL_KEYDOWN:
			CEGUI::System::getSingleton().injectKeyDown(e.key.keysym.scancode);
			if((e.key.keysym.unicode & 0xFF80) == 0)
			{
				CEGUI::System::getSingleton().injectChar(e.key.keysym.unicode & 0x7F);
			}
			break;

		case SDL_KEYUP:
			CEGUI::System::getSingleton().injectKeyUp(e.key.keysym.scancode);
			break;

		case SDL_QUIT:
			bQuit = true;
			break;

		case SDL_VIDEORESIZE:
			CEGUI::System::getSingleton().notifyDisplaySizeChanged(CEGUI::Size((float)e.resize.w, (float)e.resize.h));
			break;
		}
	}
}

void CMainFrame::HandleMouseDown(Uint8 uiButton)
{
	switch(uiButton)
	{
	case SDL_BUTTON_LEFT:
		CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::LeftButton);
		break;

	case SDL_BUTTON_MIDDLE:
		CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::MiddleButton);
		break;

	case SDL_BUTTON_RIGHT:
		CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::RightButton);
		m_bRenderGUI = !m_bRenderGUI;
		break;

	case SDL_BUTTON_WHEELDOWN:
		CEGUI::System::getSingleton().injectMouseWheelChange(-1);
		break;

	case SDL_BUTTON_WHEELUP:
		CEGUI::System::getSingleton().injectMouseWheelChange(+1);
		break;

	default:
		cout << "HandleMouseDown ignored '" << static_cast<int>(uiButton) << "'" << endl ;
		break;
	}
}

void CMainFrame::HandleMouseUp(Uint8 uiButton)
{
	switch(uiButton)
	{
	case SDL_BUTTON_LEFT:
		CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::LeftButton);
		break;

	case SDL_BUTTON_MIDDLE:
		CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::MiddleButton);
		break;

	case SDL_BUTTON_RIGHT:
		CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::RightButton);
		break;

	case SDL_BUTTON_WHEELDOWN:
		break;

	case SDL_BUTTON_WHEELUP:
		break;

	default:
		cout << "HandleMouseUp ignored '" << static_cast<int>(uiButton) << "'" << endl ;
		break;
	}
}

void CMainFrame::InjectTimePulse(double& dLastTimePulse)
{
	double dCurrentTimePulse = 0.001 * SDL_GetTicks();
	CEGUI::System::getSingleton().injectTimePulse(
		static_cast<float>(dCurrentTimePulse - dLastTimePulse));
	dLastTimePulse = dCurrentTimePulse ;
}

void CMainFrame::Init()
{
	SDL_Surface& screen = InitSDL();
	CEGUI::WindowManager& winManager = InitCEGUI(screen);

	CreateGUI(winManager);

	m_pRenderer = new CRenderer;
	m_pRenderer->Init();

	m_pScene = new CScene;
	m_pScene->Init(DEFAULT_FILE_NAME);
}

void CMainFrame::Render()
{
	glClear(GL_COLOR_BUFFER_BIT);

	m_pRenderer->Render(m_pScene);
	RenderGUI();

	SDL_GL_SwapBuffers();
}

void CMainFrame::MainLoop()
{
	bool bQquit = false ;

	double dLastTimePulse = 0.001 * static_cast<double>(SDL_GetTicks());

	while(!bQquit)
	{
		HandleInput(bQquit);
		InjectTimePulse(dLastTimePulse);

		Render();
	}
}

void CMainFrame::ReloadScene(const string& strFileName)
{
	delete m_pScene;

	m_pScene = new CScene;
	m_pScene->Init(strFileName);
}